home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #4
/
Amiga Plus CD - 2000 - No. 4.iso
/
Tools
/
Emulatoren
/
UAE0.6.4
/
src
/
cpuopti.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-27
|
3KB
|
169 lines
/*
* UAE - The Un*x Amiga Emulator
*
* cpuopti.c - Small optimizer for cpu*.s files
* Based on work by Tauno Taipaleenmaki
*
* Copyright 1996 Bernd Schmidt
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include <ctype.h>
#include "options.h"
struct line {
struct line *next, *prev;
int delete;
char *data;
};
struct func {
struct line *first_line, *last_line;
int initial_offset;
};
static void oops(void)
{
fprintf(stderr, "Corrupted assembly file!\n");
abort();
}
static char * match(struct line *l, const char *m)
{
char *str = l->data;
int len = strlen(m);
while (isspace(*str))
str++;
if (strncmp(str, m, strlen(m)) != 0)
return NULL;
return str + len;
}
static void do_function(struct func *f)
{
int pops_at_end = 0;
struct line *l, *fl;
char *s, *s2;
int in_pop_area = 1;
f->initial_offset = 0;
l = f->last_line;
fl = f->first_line;
if (!match(l,"ret"))
oops();
l = l->prev;
while (!match(fl, "op_"))
fl = fl->next;
fl = fl->next;
s = match(l, "addl $");
s2 = match(fl, "subl $");
if (s && s2 && strcmp(s,s2) == 0) {
int v = 0;
while (isdigit(*s)) {
v = v * 10 + (*s) - '0';
s++;
}
if (strcmp(s, ",%esp") == 0) {
f->initial_offset = v;
l->delete = 2;
fl->delete = 3;
l = l->prev;
fl = fl->next;
} else
in_pop_area = 0;
}
while (in_pop_area) {
char *popm, *pushm;
popm = match(l, "popl %");
pushm = match(fl, "pushl %");
if (popm && pushm && strcmp(pushm, popm) == 0) {
pops_at_end++;
fl->delete = l->delete = 1;
} else
in_pop_area = 0;
l = l->prev;
fl = fl->next;
}
if (f->initial_offset)
f->initial_offset += 4 * pops_at_end;
}
static void output_function(struct func *f)
{
struct line *l = f->first_line;
while (l) {
switch (l->delete) {
case 1:
break;
case 0:
printf("%s\n", l->data);
break;
case 2:
if (f->initial_offset)
printf("\taddl $%d,%%esp\n", f->initial_offset);
break;
case 3:
if (f->initial_offset)
printf("\tsubl $%d,%%esp\n", f->initial_offset);
break;
}
l = l->next;
}
}
int main(int argc, char **argv)
{
char tmp[4096];
for(;;) {
char *s;
if ((fgets(tmp, 4095, stdin)) == NULL)
break;
s = strchr (tmp, '\n');
if (s != NULL)
*s = 0;
if (strncmp(tmp, ".globl op_", 10) == 0) {
struct line *first_line = NULL, *prev = NULL;
struct line **nextp = &first_line;
struct func f;
do {
struct line *current;
if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) {
current = *nextp = (struct line *)malloc(sizeof (struct line));
nextp = ¤t->next;
current->prev = prev; prev = current;
current->next = NULL;
current->delete = 0;
current->data = my_strdup (tmp);
}
if ((fgets(tmp, 4095, stdin)) == NULL)
oops();
s = strchr (tmp, '\n');
if (s != NULL)
*s = 0;
} while (strncmp (tmp,".Lfe", 4) != 0);
f.first_line = first_line;
f.last_line = prev;
do_function(&f);
output_function(&f);
}
printf("%s\n", tmp);
}
return 0;
}